package org.huzhp.gateway.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.server.ResponseStatusException;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 权限认证拦截器
 * @Author: huzp
 * @CreateDate: 2020/3/13 13:02
 * @Version: 1.0
 */
@Component
public class AuthGatewayFilterFactory extends CommonGatewayFilterFactory<AuthGatewayFilterFactory.Config> {

    private static final Logger logger = LoggerFactory.getLogger(AuthGatewayFilterFactory.class);

    private static final String TOKEN_HEADER_PARAM = "token";

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private Environment env;

    public AuthGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("authType", "statics", "excludes");
    }


    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            if (checkStaticResource(config.isStatics(), exchange.getRequest())) {
                return chain.filter(exchange);
            }
            String token = exchange.getRequest().getHeaders().getFirst(TOKEN_HEADER_PARAM);
            if (token == null) {
                logger.info("missing token header value");
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "missing token header value");
            }

            requestAuth(config.getAuthType(), token);
            return chain.filter(exchange);

        };
    }

    private void requestAuth(int authType, String token) {
        String authServer = env.getProperty("auth.server");
        switch (authType) {
            case 1:
                checkAuthTypeZero(authServer, token);
                break;
            default:
                checkAuthTypeZero(authServer, token);
                break;
        }
    }

    private void checkAuthTypeZero(String authServer, String token) {
        try {
            Map map = restTemplate.getForObject(authServer + "/oauth/check_token?token={token}", Map.class, new HashMap() {{
                put("token", token);
            }});
            if (!Boolean.parseBoolean(map.get("active").toString())) {
                logger.info("token valid error");
                throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "token valid error");
            }
        } catch (RestClientException e) {
            logger.info("token valid error");
            throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "token valid error");
        }
    }


    public static class Config {
        //校验类型0-只需要校验token, 1-校验token与路由资源的关系
        private int authType;

        //是否过滤静态资源
        private boolean statics;

        //排除请求后缀
        private String excludes;

        public int getAuthType() {
            return authType;
        }

        public void setAuthType(int authType) {
            this.authType = authType;
        }

        public boolean isStatics() {
            return statics;
        }

        public void setStatics(boolean statics) {
            this.statics = statics;
        }

        public String getExcludes() {
            return excludes;
        }

        public void setExcludes(String excludes) {
            this.excludes = excludes;
        }
    }
}
